import speech_recognition as sr
import asyncio
import websockets
import base64
import numpy as np
import pygame
from scipy.io.wavfile import write
from pydub import AudioSegment
import wave
import os
import subprocess

class SpeechDetector:
    def __init__(self):
        self.uri = ["ws://202.114.212.194:50512/audio","ws://202.114.212.193:50512/audio"]
        pygame.init()  # 初始化pygame用于音频播放
        pygame.mixer.init(frequency=16000, size=-16, channels=1, buffer=512)  # 设置音频参数

    async def communicate(self):
        recognizer = sr.Recognizer()
        with sr.Microphone() as source:
            recognizer.adjust_for_ambient_noise(source)
            key=0
            while True:
                try:
                    print("请说话：")
                    audio = recognizer.listen(source, timeout=5)
                    print('finish recording, saving')
                    audio_pcm16k16bit = audio.get_raw_data(
                        convert_width=2, convert_rate=16000
                        # mono=True
                    )

                    # 将音频数据转换为单声道
                    # audio_pcm16k16bit_mono = self.convert_to_mono(audio_pcm16k16bit)
                    print(f"trying to connect {key}")
                    async with websockets.connect(self.uri[key]) as websocket:
                        # 发送音频数据
                        await websocket.send(audio_pcm16k16bit)

                        # 音频结束标志，不知道需不需要
                        await websocket.send(b'')

                        # Receive and process the transcription result
                        
                        audio_data = bytearray()
                        while True:
                            message = await websocket.recv()
                            if isinstance(message, str):
                                print("Transcription:", message)
                            elif isinstance(message, bytes):
                                if len(message) == 0:
                                    break
                                audio_data.extend(message)

                        # 如果接收到的是完整的音频帧，则尝试播放
                        if len(audio_data) > 0:
                            # 将音频数据保存到临时文件
                            temp_wav_path = 'temp_audio.wav'
                            # Convert bytearray to numpy array
                            audio_np = np.frombuffer(audio_data, dtype=np.float32)
                            
                            # Save the received audio data to a file
                            write(temp_wav_path, 24000, audio_np)
                            print("Received audio and saved to received_audio.wav")

                            # 使用 ffmpeg 播放音频
                            self.play_audio_with_ffmpeg(temp_wav_path)

                            # 清空已播放的数据
                            audio_data = bytearray()

                except (ConnectionRefusedError,websockets.exceptions.ConnectionClosedError):
                    print("Connection closed by, trying to switch")
                    reconnection_wav_path='auto_change_network.wav'
                    self.play_audio_with_ffmpeg(reconnection_wav_path)
                    await asyncio.sleep(0.1)
                    key=(key+1)%2


                except sr.WaitTimeoutError:
                    print("录音超时，未检测到声音")
                except sr.RequestError as e:
                    print("请求错误：", e)
                except sr.UnknownValueError:
                    print("无法识别语音")

    def play_audio_with_ffmpeg(self, audio_file):
        """
        使用 ffmpeg 播放音频文件
        :param audio_file: 音频文件的路径
        """
        # 检查输入文件是否存在
        if not os.path.isfile(audio_file):
            raise FileNotFoundError(f"音频文件未找到: {audio_file}")

        # 构建 FFmpeg 命令
        command = [
            'ffplay',
            '-i', audio_file,          # 指定输入文件
            '-nodisp',                # 不显示 GUI（此选项在某些版本中不可用）
            '-autoexit',               # 播放完成后自动退出
            '-hide_banner',            # 隐藏启动横幅
            '-loglevel', 'quiet'      # 关闭日志输出
        ]

        try:
            # 执行命令
            result = subprocess.run(command, capture_output=True, text=True, check=True)
            print(f"成功播放音频: {audio_file}")
        except subprocess.CalledProcessError as e:
            print(f"播放过程中发生错误: {e}")
            print("FFplay 错误输出:")
            print(e.stderr)

# 主函数
async def main():
    vc = SpeechDetector()
    await vc.communicate()

# 运行主函数
if __name__ == "__main__":
    asyncio.run(main())